﻿using System.ComponentModel;
using System.Windows;
using personalplaner.common.mvvm;
using personalplaner.common.plugins;
using personalplaner.business.stamm;
using personalplaner.common.mvvm.mediator;
using System.Collections.Generic;
using personalplaner.gui.plugins.dienstplan.views;
using personalplaner.common;
using personalplaner.gui.common;
using System.Collections.ObjectModel;
using personalplaner.servicemodel.dataaccess;
using personalplaner.common.mvvm.common;
using System.Linq;
using personalplaner.business;
using System;
using System.Windows.Data;

namespace personalplaner.gui.plugins.dienstplan.viewmodels
{
    public class DienstPlanPluginViewModel : BaseViewModel, IDienstPlanControler
    {
        public DienstPlanPluginViewModel(DependencyObject parent)
			: base(parent)
		{
		}

        #region Mediator Messages

		/// <summary>
		/// Subscribe to the mediator to receive a message when a new plan was created
		/// </summary>
		/// <param name="selectedElement"></param>
		[MediatorMessageSink("ViewControlerSelectionChanged", ParameterType = typeof(UIElement))]
		public void ViewControlerSelectionChanged(UIElement selectedElement)
		{
			if (selectedElement != SelectedArbeitsPlan)
				SelectedArbeitsPlanHeader = null;
		}

    	/// <summary>
        /// Subscribe to the mediator to receive a message when a new plan was created
        /// </summary>
        /// <param name="planid"></param>
        [MediatorMessageSink("NewPlanAdded", ParameterType = typeof(int))]
        public void NewPlanAdded(int planid)
        {
            var da = GetService<IPlanDataAccess>();
            var plan = da.GetArbeitsPlan(planid);
            ArbeitsPlanHeaderList.Insert(0, plan);
            SelectedArbeitsPlanHeader = plan;
        }

        /// <summary>
        /// Subscribe to the mediator to receive a message when a plan was deleted
        /// </summary>
        /// <param name="planid"></param>
        [MediatorMessageSink("PlanDeleted", ParameterType = typeof(int))]
        public void PlanDeleted(int planid)
        {
            ArbeitsPlanHeader plan = null;

            foreach (var itm in ArbeitsPlanHeaderList)
            {
                if (itm.PlanId == planid)
                {
                    plan = itm;
                    break;
                }
            }

            if (plan == null)
                return;

            ArbeitsPlanHeaderList.Remove(plan);
            ArbeitsPlaene.Remove(plan);

            if (ArbeitsPlaene.Keys.Count > 0)
            {
                SelectedArbeitsPlan = ArbeitsPlaene[ArbeitsPlaene.Keys.Last()];
            }
            else
            {
                SelectedArbeitsPlan = null;

                var da = GetService<IViewControler>();
                da.SelectControl(null);
            }

            var mw = GetService<IMainWindowDisplayContainer>();
            mw.IsWaitVisible = false;
        }

        /// <summary>
        /// Subscribe to the mediator to receive a message when a plan has to be removed
        /// </summary>
        /// <param name="planid"></param>
        [MediatorMessageSink("RemovePlan", ParameterType = typeof(int))]
        public void RemovePlan(int planid)
        {
            ArbeitsPlanHeader plan = null;

            foreach (var itm in ArbeitsPlanHeaderList)
            {
                if (itm.PlanId == planid)
                {
                    plan = itm;
                    break;
                }
            }

            if (plan == null)
                return;

            ArbeitsPlanHeaderList.Remove(plan);
            ArbeitsPlaene.Remove(plan);

            if (ArbeitsPlaene.Keys.Count > 0)
            {
                SelectedArbeitsPlan = ArbeitsPlaene[ArbeitsPlaene.Keys.Last()];
            }
            else
            {
                SelectedArbeitsPlan = null;

                var da = GetService<IViewControler>();
                da.SelectControl(null);

                var mw = GetService<IMainWindowDisplayContainer>();
                mw.IsWaitVisible = false;
            }
        }

        /// <summary>
        /// Subscribe to the mediator to receive a message when the list of plans has to be refreshed
        /// </summary>
        [MediatorMessageSink("RefreshPlanList")]
        public void RefreshPlanList()
        {
            _arbeitsPlaene = null;
            SelectedArbeitsPlanHeader = null;

            ArbeitsPlanHeaderList.Clear();
            var da = GetService<IPlanDataAccess>();
            var lst = da.GetArbeitsPlaene(true);
            if (lst != null)
            {
                var orderedLst = lst.OrderByDescending(ap => ap.PlanId);
                foreach (var p in orderedLst)
                    _arbeitsplanheaderlist.Add(p);
            }
            //_arbeitsplanheaderlist = lst != null ? new ObservableCollection<ArbeitsPlanHeader>(lst) : new ObservableCollection<ArbeitsPlanHeader>();
        }

        /// <summary>
        /// Subscribe to the mediator to receive a message when the services have to be updated
        /// </summary>
        [MediatorMessageSink("RefreshDienste")]
        public void RefreshDienste()
        {
            Dienste = null;
        }

        [MediatorMessageSink("ClosePlan", ParameterType = typeof(int))]
        public void ClosePlan(int planId)
        {
            ArbeitsPlanHeader plan = null;

            foreach (var itm in ArbeitsPlanHeaderList)
            {
                if (itm.PlanId == planId)
                {
                    plan = itm;
                    break;
                }
            }

            if (plan == null)
                return;

            //ArbeitsPlanHeaderList.Remove(plan);
            ArbeitsPlaene.Remove(plan);

            if (ArbeitsPlaene.Keys.Count > 0)
            {
                SelectedArbeitsPlan = ArbeitsPlaene[ArbeitsPlaene.Keys.Last()];
            }
            else
            {
                SelectedArbeitsPlan = null;

                var da = GetService<IViewControler>();
                da.SelectControl(null);

                var mw = GetService<IMainWindowDisplayContainer>();
                mw.IsWaitVisible = false;
            }
        }

        #endregion

        #region Properties

        public ICollectionView DiensteView { get; set; }

        IList<Dienst> _dienste;
        public IList<Dienst> Dienste
        {
            get
            {
                if (Designer.IsDesignMode)
                    return new ObservableCollection<Dienst>();

                if (_dienste == null)
                {
                    //get the data access via the service locator.
                    var da = GetService<IDiensteDataAccess>();
                    var lst = da.GetDienste(false, true);
                    _dienste = lst != null ? new ObservableCollection<Dienst>(lst) : new ObservableCollection<Dienst>();

                    DiensteView = CollectionViewSource.GetDefaultView(_dienste);

                    if (_dienste.Count > 0)
                        SelectedDienst = _dienste[0];
                }
                return _dienste;
            }
            set
            {
                _dienste = value;
                RaisePropertyChanged("Dienste");
            }
        }

        IList<ArbeitsPlanHeader> _arbeitsplanheaderlist;
        public IList<ArbeitsPlanHeader> ArbeitsPlanHeaderList
        {
            get
            {
                if (Designer.IsDesignMode)
                    return new ObservableCollection<ArbeitsPlanHeader>();

                if (_arbeitsplanheaderlist == null)
                {
                    var da = GetService<IPlanDataAccess>();
                    var lst = da.GetArbeitsPlaene(true);
                    _arbeitsplanheaderlist = lst != null ? new ObservableCollection<ArbeitsPlanHeader>(lst.OrderByDescending(ap => ap.PlanId)) : new ObservableCollection<ArbeitsPlanHeader>();
                }
                return _arbeitsplanheaderlist;
            }
        }

        ArbeitsPlanHeader _selectedArbeitsPlanHeader;
        public ArbeitsPlanHeader SelectedArbeitsPlanHeader
        {
            get { return _selectedArbeitsPlanHeader; }
            set
            {
                var mw = GetService<IMainWindowDisplayContainer>();
                mw.IsWaitVisible = true;

                using (new WaitCursor())
                {
                    _selectedArbeitsPlanHeader = value;
                    RaisePropertyChanged("SelectedArbeitsPlanHeader");

                    if (value == null)
                    {
                        SelectedArbeitsPlan = null;                        
                        return;
                    }

                    if (!ArbeitsPlaene.ContainsKey(value))
                    {
                        ArbeitsPlaene.Add(value, new DienstPlanView(value.PlanId, this));
                    }

                    SelectedArbeitsPlan = ArbeitsPlaene[value];
                }
            }
        }

        Dictionary<ArbeitsPlanHeader, DienstPlanView> _arbeitsPlaene;
        public Dictionary<ArbeitsPlanHeader, DienstPlanView> ArbeitsPlaene
        {
            get
            {
                if (_arbeitsPlaene == null)
                    _arbeitsPlaene = new Dictionary<ArbeitsPlanHeader, DienstPlanView>();
                return _arbeitsPlaene;
            }
        }

        DienstPlanView _selectedArbeitsPlan;
        public DienstPlanView SelectedArbeitsPlan
        {
            get { return _selectedArbeitsPlan; }
            set
            {
                _selectedArbeitsPlan = value;
                RaisePropertyChanged("SelectedArbeitsPlan");

                if (value == null)
                    return;

                var da = GetService<IViewControler>();
                da.SelectControl(value);
                
                foreach (var key in ArbeitsPlaene.Keys)
                {
                    if (ArbeitsPlaene[key] == value)
                    {
                        if (SelectedArbeitsPlanHeader != key)
                        {
                            _selectedArbeitsPlanHeader = key;
                            RaisePropertyChanged("SelectedArbeitsPlanHeader");
                        }
                        break;
                    }
                }

            }
        }

        string _filterString;
        public string FilterString
        {
            get
            {
                return _filterString;
            }
            set
            {
                _filterString = value;
                RaisePropertyChanged("FilterString");

                RefreshFilter();
            }
        }

        #endregion

        #region IDienstPlanControler Members

        Dienst _selectedDienst;
        public Dienst SelectedDienst
        {
            get
            {
                return _selectedDienst;
            }
            set
            {
                _selectedDienst = value;
                RaisePropertyChanged("SelectedDienst");
            }
        }

        System.Windows.Media.Color _selectedColor = System.Windows.Media.Colors.Transparent;
        public System.Windows.Media.Color SelectedColor
        {
            get
            {
                return _selectedColor;
            }
            set
            {
                _selectedColor = value;
                RaisePropertyChanged("SelectedColor");
            }
        }

        #endregion

        #region Filter

        #region Implementation

        IList<Dienst> _displayedItems;

        /// <summary>
        /// refreshes the filtering of the combobox according to the string in <see cref="FilterString"/>
        /// </summary>
        private void RefreshFilter()
        {
            // only filter if a path is set
            //if (string.IsNullOrEmpty(FilterString))
            //    return;

            //var source = Dienste as ICollectionView;
            var source = DiensteView;
            if (source != null)
            {
                _displayedItems = new List<Dienst>();

                //FilterString = filterText;

                // remove previous filters
                if (source.Filter != null)
                    source.Filter -= new Predicate<object>(Filter);

                source.Filter += new Predicate<object>(Filter);

                if (_displayedItems.Count > 0)
                    SelectedDienst = _displayedItems[0];
            }
        }

        /// <summary>
        /// method that gets called by the predicate in the ICollectionView.Filter that filters the entries in the dropdown
        /// according to the string in <see cref="FilterString"/>
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool Filter(object obj)
        {
            // no filter is set
            if (string.IsNullOrEmpty(FilterString))
                return true;

            // get the value from the property out of the bound object
            var value = obj as Dienst;
            if (value == null)
                return false;
            
            if (string.IsNullOrEmpty(value.DienstName))
                return false;

            //bool isFiltered = value.DienstName.IndexOf(FilterString, StringComparison.CurrentCultureIgnoreCase) >= 0;
            bool isFiltered = value.DienstName.StartsWith(FilterString, StringComparison.CurrentCultureIgnoreCase);

            if (isFiltered)
                _displayedItems.Add(value);

            return isFiltered;
        }

        #endregion

        #endregion
    }
}
